package com.xuelang.pipeline.infrastructure.application.repository;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xuelang.pipeline.client.application.dto.ComponentQuery;
import com.xuelang.pipeline.client.common.result.PageRecord;
import com.xuelang.pipeline.domain.application.Component;
import com.xuelang.pipeline.domain.application.repository.ComponentRepository;
import com.xuelang.pipeline.infrastructure.application.converter.ComponentToComponentDOConverter;
import com.xuelang.pipeline.infrastructure.application.dataobject.ComponentDO;
import com.xuelang.pipeline.infrastructure.application.mapper.ComponentMapper;
import dm.jdbc.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 组件仓库实现类
 *
 * @author xiwen.zxg
 * @since 2024/5/15
 */
@Slf4j
@Repository
public class ComponentRepositoryImpl implements ComponentRepository {

    @Autowired
    ComponentMapper componentMapper;

    @Override
    public PageRecord<Component> pageList(long currentPage, long pageSize, ComponentQuery componentQuery) {
        currentPage = currentPage < 1 ? 1 : currentPage;
        pageSize = pageSize < 1 ? 10 : pageSize;
        Page<ComponentDO> page = new Page<>(currentPage, pageSize);
        LambdaQueryWrapper<ComponentDO> wrapper = Wrappers.lambdaQuery(ComponentDO.class);
        if (componentQuery != null) {
            if (StringUtils.isNotBlank(componentQuery.getCode())) {
                wrapper.like(ComponentDO::getCode, componentQuery.getCode());
            }
            if (StringUtils.isNotBlank(componentQuery.getName())) {
                wrapper.like(ComponentDO::getName, componentQuery.getName());
            }
            if (componentQuery.getComponentType() != null && componentQuery.getComponentType() != 0) {
                wrapper.eq(ComponentDO::getComponentType, componentQuery.getComponentType());
            }
            if (StringUtils.isNotBlank(componentQuery.getProgramLanguage())) {
                wrapper.eq(ComponentDO::getProgramLanguage, componentQuery.getProgramLanguage());
            }
            if (StringUtils.isNotBlank(componentQuery.getCodeRepository())) {
                wrapper.eq(ComponentDO::getCodeRepository, componentQuery.getCodeRepository());
            }
            if (StringUtils.isNotBlank(componentQuery.getGitToken())) {
                wrapper.eq(ComponentDO::getGitToken, componentQuery.getGitToken());
            }
            if (StringUtils.isNotBlank(componentQuery.getApplicationCode())) {
                wrapper.eq(ComponentDO::getApplicationCode, componentQuery.getApplicationCode());
            }
        }
        componentMapper.selectPage(page, wrapper);
        return new PageRecord<>(
                page.getCurrent(),
                page.getSize(),
                page.getTotal(),
                page.getPages(),
                page.getRecords().stream().map(ComponentToComponentDOConverter.INSTANCE::componentDOToComponent).collect(Collectors.toList())
        );
    }

    @Override
    public List<Component> list(ComponentQuery componentQuery) {
        LambdaQueryWrapper<ComponentDO> wrapper = Wrappers.lambdaQuery(ComponentDO.class);
        if (componentQuery != null) {
            if (StringUtils.isNotBlank(componentQuery.getCode())) {
                wrapper.like(ComponentDO::getCode, componentQuery.getCode());
            }
            if (StringUtils.isNotBlank(componentQuery.getName())) {
                wrapper.like(ComponentDO::getName, componentQuery.getName());
            }
            if (componentQuery.getComponentType() != null && componentQuery.getComponentType() != 0) {
                wrapper.eq(ComponentDO::getComponentType, componentQuery.getComponentType());
            }
            if (StringUtils.isNotBlank(componentQuery.getProgramLanguage())) {
                wrapper.eq(ComponentDO::getProgramLanguage, componentQuery.getProgramLanguage());
            }
            if (StringUtils.isNotBlank(componentQuery.getCodeRepository())) {
                wrapper.eq(ComponentDO::getCodeRepository, componentQuery.getCodeRepository());
            }
            if (StringUtils.isNotBlank(componentQuery.getGitToken())) {
                wrapper.eq(ComponentDO::getGitToken, componentQuery.getGitToken());
            }
            if (StringUtils.isNotBlank(componentQuery.getApplicationCode())) {
                wrapper.eq(ComponentDO::getApplicationCode, componentQuery.getApplicationCode());
            }
        }
        return componentMapper.selectList(wrapper).stream()
                .map(ComponentToComponentDOConverter.INSTANCE::componentDOToComponent).collect(Collectors.toList());
    }

    @Override
    public Boolean save(Component component) {
        return componentMapper.insert(ComponentToComponentDOConverter.INSTANCE.componentToComponentDO(component)) == 1;
    }

    @Override
    public Boolean update(Component component) {
        return componentMapper.update(
                ComponentToComponentDOConverter.INSTANCE.componentToComponentDO(component),
                Wrappers.lambdaQuery(ComponentDO.class)
                        .eq(ComponentDO::getApplicationCode, component.getApplicationCode())
                        .eq(ComponentDO::getCode, component.getCode())) == 1;
    }

    @Override
    public Boolean delete(String componentLabel) {
        return componentMapper.delete(Wrappers.lambdaQuery(ComponentDO.class)
                .eq(ComponentDO::getLabel, componentLabel)) == 1;
    }

    @Override
    public Component query(String componentLabel) {
        ComponentDO componentDO = componentMapper.selectOne(Wrappers.lambdaQuery(ComponentDO.class)
                .eq(ComponentDO::getLabel, componentLabel));
        return ComponentToComponentDOConverter.INSTANCE.componentDOToComponent(componentDO);
    }

    @Override
    public Boolean existsCode(String applicationCode, String code) {
        return componentMapper.exists(Wrappers.lambdaQuery(ComponentDO.class)
                .eq(ComponentDO::getApplicationCode, applicationCode)
                .eq(ComponentDO::getCode, code));
    }

    @Override
    public Boolean existsLabel(String uniqueLabel) {
        return componentMapper.exists(Wrappers.lambdaQuery(ComponentDO.class)
                .eq(ComponentDO::getLabel, uniqueLabel));
    }

    @Override
    public Boolean existsName(String applicationCode, String code, String name) {
        List<ComponentDO> componentDOS = componentMapper.selectList(Wrappers.lambdaQuery(ComponentDO.class)
                .eq(ComponentDO::getApplicationCode, applicationCode)
                .eq(ComponentDO::getName, name));
        if (ObjectUtil.isEmpty(componentDOS)) {
            return false;
        }
        return componentDOS.stream().anyMatch(componentDO -> !StringUtil.equals(code, componentDO.getCode()));
    }

    @Override
    public Component queryById(Long id) {
        ComponentDO componentDO = componentMapper.selectById(id);
        return ComponentToComponentDOConverter.INSTANCE.componentDOToComponent(componentDO);
    }
}
